import numpy as np
import pandas as pd
from pandas import DataFrame
from sklearn.model_selection import train_test_split

from kaggle.utils.data_preprocessor import preprocess_data

train_filepath = 'data/train.csv'
test_filepath = 'data/test.csv'
# 预处理数据
_, X, y = preprocess_data(train_filepath, np.array(['Id']), 'Id', 'SalePrice')

# 拆分训练和验证数据
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.1, random_state=42)


# 定义损失函数
def compute_loss(y_train, y_pred):
    mse = np.mean((y_train - y_pred) ** 2)
    return mse


class SimpleLinearRegression:
    def __init__(self, learning_rate=0.01, num_epochs=100):
        self.weight = None
        self.bias = 0
        self.learning_rate = learning_rate
        self.num_epochs = num_epochs
        self.last_loss = 0

    def fit(self, X, y):
        m, n = X.shape
        self.weight = np.zeros(n)

        for epoch in range(self.num_epochs):
            y_pred = np.dot(X, self.weight) + self.bias

            # 计算梯度
            dw = (1 / m) * np.dot(X.T, y_pred - y)
            db = (1 / m) * np.sum(y_pred - y)

            self.weight -= self.learning_rate * dw
            self.bias -= self.learning_rate * db

            loss = compute_loss(y, y_pred)
            if epoch % 10 == 0:
                print(f'epoch: {epoch:6d}, loss={loss:.3f}, delta_loss={self.last_loss - loss:.3f}')

                self.last_loss = loss

    def predict(self, X):
        y_pred = np.dot(X, self.weight) + self.bias
        return np.array(y_pred)


def calculate_pairwise_rmse(arr_true, arr_pred):
    if arr_true.shape != arr_pred.shape:
        raise ValueError("The shapes of the two arrays must be the same")

    # Calculate RMSE
    differences = arr_true - arr_pred
    squared_differences = differences ** 2
    pairwise_rmse = np.sqrt(np.mean(squared_differences))

    # Calculate error percentage
    error_percentage = np.mean(np.abs(differences) / arr_true) * 100

    return pairwise_rmse, error_percentage


model = SimpleLinearRegression(learning_rate=0.0025, num_epochs=10000 * 10)
# model.fit(X_train, y_train)
# y_val_pred = model.predict(X_val)
# pairwise_rmse, error_percent = calculate_pairwise_rmse(y_val, y_val_pred)
# print(f'rmse: {pairwise_rmse:.2f}, error_percent: {error_percent:.2f}')

model.fit(X, y)
# 预处理数据
ids, X_test, _ = preprocess_data(test_filepath, np.array(['Id']), 'Id', 'SalePrice')
y_test_pred = model.predict(X_test)
submission_df = pd.DataFrame({
    'Id': ids,
    'SalePrice': y_test_pred
})
submission_df.to_csv('./data/submission_lr.csv', index=False)
